 /*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 /**
 * Project  : EasyAvatar-Android
 * Package  : net.solosky.easyavatar.utils
 * File     : ContactManager.java
 * Author   : solosky < solosky772@qq.com >
 * Created  : Nov 27, 2011
 * License  : Apache License 2.0 
 */
package net.solosky.easyavatar.utils;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.solosky.easyavatar.R;
import net.solosky.easyavatar.api.Friend;
import net.solosky.easyavatar.bean.Contact;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.Contacts.People;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

/**
 *
 * 管理联系人的实用工具类
 *
 * @author solosky <solosky772@qq.com>
 *
 */
public class ContactManager {
	/**手机中联系人列表*/
	private List<Contact> contactList;
	
	public ContactManager(){
		this.contactList = new ArrayList<Contact>();
	}
	
	
	/**
	 * 加载手机中所有的联系人
	 * @param context
	 */
	public void loadAllContacts(Context context){
		Map<String, Contact> contactMap = new HashMap<String, Contact>();
		Cursor cur = context.getContentResolver().query(Data.CONTENT_URI,
		              new String[] {Data.RAW_CONTACT_ID, Data.MIMETYPE, Phone.NUMBER, Phone.TYPE, Phone.LABEL, Photo.PHOTO},
		             null, null, null);
	   if (cur.moveToFirst()) {
	        do {
	        	String cId      = cur.getString(0);
	        	Contact contact = contactMap.get(cId);
	        	if(contact==null){
	        		contact = new Contact();
	        		contact.setId(cId);
	        		contactMap.put(cId, contact);
	        		contactList.add(contact);
	        	}
	        	
	        	String mimeType = cur.getString(1);
	        	if(mimeType.equals("vnd.android.cursor.item/name")){
	        		contact.setName(cur.getString(2));
	        	}else if(mimeType.equals("vnd.android.cursor.item/phone_v2")){
	        		contact.setMobile(cur.getString(2));
	        	}else if(mimeType.equals(Photo.CONTENT_ITEM_TYPE)){
	        		byte[] data = cur.getBlob(5);
	        		if(data!=null){
		        		Bitmap head = BitmapFactory.decodeStream(new ByteArrayInputStream(data));
		        		contact.setHead(head);
	        		}
	        	}else{
	        	}
	        } while (cur.moveToNext());
	    }
	   
	   //删除没有手机号码和名字的联系人
	   Iterator<Contact> it = contactList.iterator();
		while(it.hasNext()){
			Contact contact = it.next();
			if(TextUtils.isEmpty(contact.getName()) || TextUtils.isEmpty(contact.getMobile())){
				it.remove();
				if(contact.getHead()!=null){
					contact.getHead().recycle();
					contact.setHead(null);
				}
			}
		}
	   
	   //联系人按拼音排序
	   Collections.sort(contactList, new Comparator<Contact>() {
		@Override
		public int compare(Contact lhs, Contact rhs) {
			return lhs.getPinyin().compareTo(rhs.getPinyin());
		}
	   });
	}
	
	/**
	 * 获得联系人数量
	 * @return
	 */
	public int getContactNum(){
		return this.contactList.size();
	}
	
	
	/**
	 * 获得联系人列表
	 * @return
	 */
	public List<Contact> getContactList() {
		return Collections.unmodifiableList(contactList);
	}
	
	/**
	 * 根据手机号码查找联系人
	 * @param mobile
	 */
	public Contact findContactByMobile(String mobile){
		for(Contact contact:contactList){
			if(contact.getMobile().endsWith(mobile)){
				return contact;
			}
		}
		return null;
	}
	
	/**
	 * 根据联系人编号查找联系人
	 * @param mobile
	 */
	public Contact findContactById(String cid){
		for(Contact contact:contactList){
			if(contact.getId().equals(cid)){
				return contact;
			}
		}
		return null;
	}
	
	/**
	 * 获取自己的手机联系人对象
	 * @param context
	 * @return
	 */
	public Contact getMySelfContact(Context context){
		SharedPreferences prefs = context.getSharedPreferences(Constants.DEFAULT_PREFS, 0);
		String myMobile = prefs.getString("my.mobile", null);
		if(myMobile==null){
			 TelephonyManager phoneMgr=(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
			 myMobile = phoneMgr.getLine1Number();
		}
		if(myMobile!=null){
			Contact contact = findContactByMobile(myMobile);
			if(contact==null){
				contact = new Contact();
				contact.setMobile(myMobile);
				contact.setName(Views.S(R.string.my_self));
				insertContact(context, contact);
				contactList.add(contact);
			}
			return contact;
		}else{
			return null;
		}
	}
	
	/**
	 * 插入一个新的联系人
	 * 部分代码来自：http://www.cnblogs.com/linjiqin/archive/2011/05/30/2063669.html
	 * @param context
	 * @param contact
	 */
	public void insertContact(Context context, Contact contact){
		ContentValues values = new ContentValues(); // 首先向RawContacts.CONTENT_URI执行一个空值插入，目的是获取系统返回的rawContactId
		Uri rawContactUri = context.getContentResolver().insert(
				RawContacts.CONTENT_URI, values);
		long rawContactId = ContentUris.parseId(rawContactUri);

		// 往data表入姓名数据
		values.clear();
		values.put(Data.RAW_CONTACT_ID, rawContactId);
		values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
		values.put(StructuredName.GIVEN_NAME, contact.getName());
		context.getContentResolver().insert(
				android.provider.ContactsContract.Data.CONTENT_URI, values);

		// 往data表入电话数据
		values.clear();
		values.put(
				android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID,
				rawContactId);
		values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
		values.put(Phone.NUMBER, contact.getMobile());
		values.put(Phone.TYPE, Phone.TYPE_MOBILE);
		context.getContentResolver().insert(
				android.provider.ContactsContract.Data.CONTENT_URI, values);
		
		contact.setId(""+rawContactId);
	}
	 
	/**
	 * 根据好友匹配最佳的联系人
	 * 匹配方法：将好友的名字和联系人名字的拼音计算相似度，大于一个阈值就可以认为匹配
	 * @param friend
	 * @return
	 */
	public Contact findMostMatchedContact(Friend friend){
		Contact matchedContact = null;
		double matchedDistance = -1;
		for(Contact contact:contactList){
			double nowDistance = LD.sim(friend.getPinyin(), contact.getPinyin());
			if(nowDistance>matchedDistance){
				matchedContact = contact;
				matchedDistance = nowDistance;
			}
		}
		return matchedDistance>0.8 ? matchedContact : null;
	}
	
	/**
	 * 设置联系人头像
	 * 代码来自 http://blog.smalldemon.org/?p=54 并做了小的改动
	 * @param context
	 * @param bytes
	 * @param personId
	 * @param Sync
	 */
	public void setContactPhoto(Context context, byte[] bytes,
			long personId, boolean Sync) {
		int sdkVersion = Build.VERSION.SDK_INT;
		if (sdkVersion<5) {
			Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI,
					personId);
			People.setPhotoData(context.getContentResolver(), myPerson, bytes);
			if (!Sync) {
				ContentValues values = new ContentValues();
				values.put("_sync_dirty", 0);
				context.getContentResolver().update(myPerson, values, null,
						null);
			}
		} else{
			ContentResolver c = context.getContentResolver();
			ContentValues values = new ContentValues();
			Uri u = Uri.parse("content://com.android.contacts/data");
			int photoRow = -1;
			String where = "raw_contact_id = " + personId
					+ " AND mimetype ='vnd.android.cursor.item/photo'";
			Cursor cursor = c.query(u, null, where, null, null);
			int idIdx = cursor.getColumnIndexOrThrow("_id");
			if (cursor.moveToFirst()) {
				photoRow = cursor.getInt(idIdx);
			}
			cursor.close();
			values.put("raw_contact_id", personId);
			values.put("is_super_primary", 1);
			values.put("data15", bytes);
			values.put("mimetype", "vnd.android.cursor.item/photo");
			if (photoRow >= 0) {
				c.update(u, values, " _id= " + photoRow, null);
			} else {
				c.insert(u, values);
			}
			if (!Sync) {
				u = Uri.withAppendedPath(
						Uri.parse("content://com.android.contacts/raw_contacts"),
						String.valueOf(personId));
				values = new ContentValues();
				values.put("dirty", 0);
				c.update(u, values, null, null);
			}
		}
	}
}
